package com.rmc.verifycode.util;

import com.rmc.http.accesser.HttpAccesser;
import com.rmc.http.accesser.HttpException;
import com.rmc.verifycode.Char;
import com.rmc.verifycode.CharGroup;
import com.rmc.verifycode.matrix.BitMatrix;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class ImageUtils {
    private static final Map<String, BlackFinder> blackFinderMap = new HashMap<String, BlackFinder>();
    private static final BlackFinder DEFAULT_BLACK_FINDER = new BlackFinder();

    public static CharGroup toCharGroup(File charImageDir) {
        String id = charImageDir.getName();
        File[] charImages = charImageDir.listFiles();

        CharGroup charGroup = new CharGroup(id);
        BlackFinder blackFinder = getBlackFinder(id);
        for (File charImage : charImages) {
            Char aChar = toChar(charImage, blackFinder);
            System.out.println(aChar);
            charGroup.add(aChar);
        }
        return charGroup;
    }

    public static BlackFinder getBlackFinder(String id) {
        BlackFinder blackFinder = blackFinderMap.get(id);
        if (blackFinder != null) return blackFinder;
        try {
            String className = "com.rmc.verifycode.blackfinder." + StringUtils.capitalize(id);
            blackFinder = (BlackFinder) Class.forName(className).newInstance();
            blackFinderMap.put(id, blackFinder);
        } catch (Exception e) {
            blackFinder = DEFAULT_BLACK_FINDER;
        }
        return blackFinder;
    }


    public static Char toChar(File charImage, BlackFinder blackFinder) {
        BufferedImage image = readImage(charImage);
        BitMatrix bitMap = blackFinder.toBitMap(image);
        String character = charImage.getName().replaceAll("\\..*|\\W|_", "");
        return new Char(bitMap, character);
    }


    public static BufferedImage readImage(File image) {
        try {
            return ImageIO.read(image);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }


    public static BufferedImage readImage(InputStream input) {
        try {
            return ImageIO.read(input);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }


    public static void downImage(String dirPath, String uri, int count) throws HttpException {
        File dir = new File(dirPath);
        HttpAccesser accesser = HttpAccesser.createHttpAccesser();
        for (int i = 1; i <= count; i++) {
            File image = accesser.buildReq(uri).submitForFile();
            try {
                FileUtils.moveFileToDirectory(image, dir, true);
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(image);
        }
    }


    public static BufferedImage toBinary(BufferedImage image) {
        BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        RenderingHints renderingHints = image.createGraphics().getRenderingHints();
        ColorConvertOp opGray =
                new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), renderingHints);
        opGray.filter(image, result);
        RescaleOp op = new RescaleOp(2f, 60f, renderingHints);
        op.filter(result, result);
        return result;
    }

    public static void writeToLocal(BufferedImage image, File dest) {
        try {
            ImageIO.write(image, "jpg", dest);
        } catch (IOException e) {
            //ignore
        }
    }

    public static void convertToBinary(File image) {
        BufferedImage bufferedImage = readImage(image);
        BufferedImage binaryImage = toBinary(bufferedImage);
        writeToLocal(binaryImage, image);
    }

    public static void main(String[] args) throws Exception {
/*        File imageDir = new File("e:\\temp\\baixing\\");
        File[] imageFiles = imageDir.listFiles();
        for (File imageFile : imageFiles) {
            convertToBinary(imageFile);
        }*/
//        BufferedImage image = readImage(new File("e:/number_red.jpg"));
//		image = toBinary(image);
//        BitMatrix bit = DEFAULT_BLACK_FINDER.toBitMap(image);
//        System.out.println("bit = \n" + bit);
//		downImage("d:\\hAdIx\\temp\\image\\",
//		          "http://sslk.bjjtgl.gov.cn/jgjww/jcaptcha", 50);
        CharGroup group = toCharGroup(new File("c:\\58.com"));
        group.save("c:\\");
        File imageDir = new File("c:\\58.com");
        File[] imageFiles = imageDir.listFiles();
        for (File imageFile : imageFiles) {
            group.match(imageFile);
        }
//        CharGroup group = CharGroup.load("e:\\Temp\\images\\58.com.verifycode");
//        System.out.println(group.toString());
//        String code = group.match(new File("e:\\Temp\\images\\showphone.jpg"));
//        System.out.println("code = " + code);
    }
}
